/*jshint esversion: 6 */ //credit to Brian on the forums for this framework! function ManhDist(token1,token2) { //Manhattan Distance in tiles between two units let AXCoord = token1.get("left"); let AYCoord = token1.get("top"); let BXCoord = token2.get("left"); let BYCoord = token2.get("top"); let diff = parseInt((Math.abs(AXCoord - BXCoord))+(Math.abs(AYCoord - BYCoord))); return (diff/70) } on('chat:message', function(msg) { if (msg.type != 'api') return; var parts = msg.content.split(' '); var command = parts.shift().substring(1); var turnorder; var turncounter; if (Campaign().get("turnorder") == "") turnorder = []; else turnorder = JSON.parse(Campaign().get("turnorder")); for (i in turnorder){ if (turnorder[i].custom == "Turn Counter"){ turncounter = turnorder[i] } } let n = turncounter.pr ||0 //log(turncounter) // Don't run if it's any other command if (command == 'combat') { if (parts.length < 2) { sendChat('SYSTEM', 'You must provide a selected token id and a target token id.'); return; } var selectedId = parts[0]; var targetId = parts[1]; // Grab tokens var selectedToken = getObj('graphic', selectedId); var targetToken = getObj('graphic', targetId); // Check if the objects aren't tokens or if the passed parameters aren't ids if (!selectedToken) { sendChat('SYSTEM', 'Selected token id not provided.'); return; } if (!targetToken) { sendChat('SYSTEM', 'Target token id not provided.'); return; } log(selectedToken.get('represents')); log(targetToken.get('represents')); //Check to make sure that the tokens represent characters if (selectedToken.get('represents') === "" || targetToken.get('represents') === ""){ sendChat('SYSTEM', 'Both tokens must be linked to characters in the journal!'); return; } // Get a variable to use as the "who" for sendChat var who = getObj('character', selectedToken.get('represents')); if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } var who2 = getObj('character', targetToken.get('represents')); if (!who2) { who2 = targetToken.get('name'); } else { who2 = 'character|' + who2.id; } var attacker = getObj('character', selectedToken.get('represents')); var defender = getObj('character', targetToken.get('represents')); let AName = attacker.get('name'); let DName = defender.get('name'); sendChat(who, '/em attacks ' + DName + '!\n') let Chatstr = ''; //Grab basic stats let CurrHPA = findObjs({ characterid: attacker.id, name: "HP_current"})[0]; let CurrHPB = findObjs({ characterid: defender.id, name: "HP_current"})[0]; let CurrEXP = findObjs({ characterid: attacker.id, name: "EXP"})[0]; let LvA = findObjs({ characterid: attacker.id, name: "Level"})[0]; let InLvA = Number(LvA.get("current")); let LvB = findObjs({ characterid: defender.id, name: "Level"})[0]; let InLvB = Number(LvB.get("current")); let EXPA = Number(CurrEXP.get("current")); let IsPromoA = getAttrByName(attacker.id, 'isPromo'); let IsPromoB = getAttrByName(defender.id, 'isPromo'); let HPA = Number(getAttrByName(attacker.id, 'hp_current')); let HPB = Number(getAttrByName(defender.id, 'hp_current')); let StrA = Number(getAttrByName(attacker.id, 'str_total')); let StrB = Number(getAttrByName(defender.id, 'str_total')); let MagA = Number(getAttrByName(attacker.id, 'mag_total')); let MagB = Number(getAttrByName(defender.id, 'mag_total')); let SklA = Number(getAttrByName(attacker.id, 'skl_total')); let SklB = Number(getAttrByName(defender.id, 'skl_total')); let SpdA = Number(getAttrByName(attacker.id, 'spd_total')); let SpdB = Number(getAttrByName(defender.id, 'spd_total')); let LckA = Number(getAttrByName(attacker.id, 'lck_total')); let LckB = Number(getAttrByName(defender.id, 'lck_total')); let DefA = Number(getAttrByName(attacker.id, 'def_total')); let DefB = Number(getAttrByName(defender.id, 'def_total')); let ResA = Number(getAttrByName(attacker.id, 'res_total')); let ResB = Number(getAttrByName(defender.id, 'res_total')); //Grab weapon stats let WNameA = getAttrByName(attacker.id, 'repeating_weapons_$0_WName') || "Empty"; let WNameB = getAttrByName(defender.id, 'repeating_weapons_$0_WName') || "Empty"; let WTypeA = getAttrByName(attacker.id, 'repeating_weapons_$0_WType') || "Stones/Other"; let WTypeB = getAttrByName(defender.id, 'repeating_weapons_$0_WType') || "Stones/Other"; let MtA = parseInt(getAttrByName(attacker.id, 'repeating_weapons_$0_Mt')) || 0; let MtB = parseInt(getAttrByName(defender.id, 'repeating_weapons_$0_Mt')) || 0; let WtA = parseInt(getAttrByName(attacker.id, 'repeating_weapons_$0_Wt')) || 0; let WtB = parseInt(getAttrByName(defender.id, 'repeating_weapons_$0_Wt')) || 0; let Range1A = parseInt(getAttrByName(attacker.id, 'repeating_weapons_$0_Range1')) || 1; let Range1B = parseInt(getAttrByName(defender.id, 'repeating_weapons_$0_Range1')) || 1; let Range2A = parseInt(getAttrByName(attacker.id, 'repeating_weapons_$0_Range2')) || 1; let Range2B = parseInt(getAttrByName(defender.id, 'repeating_weapons_$0_Range2')) || 1; let WRankA = getAttrByName(attacker.id, 'repeating_weapons_$0_WRank') || "E"; let WRankB = getAttrByName(defender.id, 'repeating_weapons_$0_WRank') || "E"; let fIDA = getAttrByName(attacker.id, 'fid')|| "" let fIDB = getAttrByName(defender.id, 'fid')|| "" log(fIDA) log(fIDB) let UsesA; let UsesB; let AOEA = getAttrByName(attacker.id, "repeating_weapons_$0_AOE"); let AOEB = getAttrByName(defender.id, "repeating_weapons_$0_AOE"); log("AOE is " + AOEA) log("AOE is " + AOEB) //check for no rows if (fIDA == ""){ UsesA = 68932; log("No weapon! :0"); } else { UsesA = findObjs({ characterid: attacker.id, name: "repeating_weapons_"+fIDA+"_Uses"},{ caseInsensitive: true })[0]; } if (fIDB == ""){ UsesB = 68932; } else { UsesB = findObjs({ characterid: defender.id, name: "repeating_weapons_"+fIDB+"_Uses"},{ caseInsensitive: true })[0]; } log(UsesA); log(UsesB); let StrengthsA = getAttrByName(attacker.id, "repeating_weapons_$0_Strengths") || ""; let StrengthsB = getAttrByName(defender.id, "repeating_weapons_$0_Strengths") || ""; let WeaknessA = getAttrByName(attacker.id, 'weaknesses'); let WeaknessB = getAttrByName(defender.id, 'weaknesses'); //Weapon exp let SwordEXP = findObjs({ characterid: attacker.id, name: "SwordEXP", type: "attribute"})[0]; let LanceEXP = findObjs({ characterid: attacker.id, name: "LanceEXP", type: "attribute"})[0]; let AxeEXP = findObjs({ characterid: attacker.id, name: "AxeEXP", type: "attribute"})[0]; let BowEXP = findObjs({ characterid: attacker.id, name: "BowEXP", type: "attribute"})[0]; let DaggerEXP = findObjs({ characterid: attacker.id, name: "GunEXP", type: "attribute"})[0]; let GunEXP = findObjs({ characterid: attacker.id, name: "GunEXP", type: "attribute"})[0]; let DarkEXP = findObjs({ characterid: attacker.id, name: "DarkEXP", type: "attribute"})[0]; let LightEXP = findObjs({ characterid: attacker.id, name: "LightEXP", type: "attribute"})[0]; let AnimaEXP = findObjs({ characterid: attacker.id, name: "AnimaEXP", type: "attribute"})[0]; let StoneEXP = findObjs({ characterid: attacker.id, name: "StoneEXP", type: "attribute"})[0]; let StaffEXP = findObjs({ characterid: attacker.id, name: "StaffEXP", type: "attribute"})[0]; //Hit/crit/avo/dod let HitA = getAttrByName(attacker.id, 'hit'); let HitB = getAttrByName(defender.id, 'hit'); let CritA = getAttrByName(attacker.id, 'crit'); let CritB = getAttrByName(defender.id, 'crit'); let AvoA = getAttrByName(attacker.id, 'avo'); let AvoB = getAttrByName(defender.id, 'avo'); let DdgA = getAttrByName(attacker.id, 'lck_total'); let DdgB = getAttrByName(defender.id, 'lck_total'); let DmgmodA = Number(getAttrByName(attacker.id, 'Dmgmod')); let DmgmodB = Number(getAttrByName(defender.id, 'Dmgmod')); //Grab weapon ranks let SwordUA = getAttrByName(attacker.id, 'SwordU'); let LanceUA = getAttrByName(attacker.id, 'LanceU'); let AxeUA = getAttrByName(attacker.id, 'AxeU'); let BowUA = getAttrByName(attacker.id, 'BowU'); let DaggerUA = getAttrByName(attacker.id, 'DaggerU'); let GunUA = getAttrByName(attacker.id, 'GunU'); let AnimaUA = getAttrByName(attacker.id, 'AnimaU'); let LightUA = getAttrByName(attacker.id, 'LightU'); let DarkUA = getAttrByName(attacker.id, 'DarkU'); let StoneUA = getAttrByName(attacker.id, 'StoneU'); let StaffUA = getAttrByName(attacker.id, 'StaffU'); let SwordUB = getAttrByName(defender.id, 'SwordU'); let LanceUB = getAttrByName(defender.id, 'LanceU'); let AxeUB = getAttrByName(defender.id, 'AxeU'); let BowUB = getAttrByName(defender.id, 'BowU'); let DaggerUB = getAttrByName(defender.id, 'DaggerU'); let GunUB = getAttrByName(defender.id, 'GunU'); let AnimaUB = getAttrByName(defender.id, 'AnimaU'); let LightUB = getAttrByName(defender.id, 'LightU'); let DarkUB = getAttrByName(defender.id, 'DarkU'); let StoneUB = getAttrByName(defender.id, 'StoneU'); let StaffUB = getAttrByName(defender.id, 'StaffU'); const PhysWepTypes = ["Sword/Katana","Lance/Nagin.","Axe/Club","Bow/Yumi","Dagger/Shurik.","Stones/Other"]; const MWepTypes = ["Anima Magic","Light Magic","Dark Magic"]; const WepTypes = ["Sword/Katana","Lance/Nagin.","Axe/Club","Bow/Yumi","Dagger/Shurik.","Firearm/Taneg.","Anima Magic","Light Magic","Dark Magic","Stones/Other","Staves/Rods"]; const MagWeps = ["Levin Sword","Bolt Naginata","Bolt Axe","Shining Bow","Flame Shuriken"]; const PhysWeps = ["Flame Glaive","Light Rapier","Shadow Hammer"]; const WepRanks = [SwordEXP,LanceEXP,AxeEXP,BowEXP,DaggerEXP,GunEXP,AnimaEXP,LightEXP,DarkEXP,StoneEXP,StaffEXP]; const WepUA = [SwordUA,LanceUA,AxeUA,BowUA,DaggerUA,GunUA,AnimaUA,LightUA,DarkUA,StoneUA,StaffUA]; const WepUB = [SwordUB,LanceUB,AxeUB,BowUB,DaggerUB,GunUB,AnimaUB,LightUB,DarkUB,StoneUB,StaffUB]; let DmgtypeA; let DmgtypeB; let DmgA; let DmgB; let DoubleA = false; let DoubleB = false; let QuadA = false; let QuadB = false; let CanAttackA = true; let CanAttackB = true; let SkillsA = findObjs({ characterid: attacker.id, type: "ability"}); let SkillsB = findObjs({ characterid: defender.id, type: "ability"}); //Weapon Rank threshold values let WRankA_num; let WRankB_num; const LRanks = [{num: 0, rank: "E"},{num: 30, rank: "D"},{num: 70, rank: "C"},{num: 120, rank: "B"},{num: 180, rank: "A"},{num: 250, rank: "S"},{num: 999, rank: "UU"}]; //check for which rank for (var h in LRanks){ if (LRanks[h].rank == WRankA){ WRankA_num = LRanks[h].num; } } for (var j in LRanks){ if (LRanks[j].rank == WRankB){ WRankB_num = LRanks[j].num; } } log("Numerical weapon rank is " + WRankA_num); //Check to see if the weapon is usable if ((WepUA[WepTypes.indexOf(WTypeA)] == 1) && (WepRanks[WepTypes.indexOf(WTypeA)].get("current") >= WRankA_num)){ log("Attacker's weapon is usable!"); } else { log("Attacker's weapon is not usable!"); CanAttackA = false; } if ((WepUB[WepTypes.indexOf(WTypeB)] == 1) && (WepRanks[WepTypes.indexOf(WTypeB)].get("current") >= WRankB_num)){ log("Defender's weapon is usable!"); } else { log("Defender's weapon is not usable!"); CanAttackB = false; } //Check for weapon effectiveness- HAS TO BE BEFORE stat targeting calcs so it can factor in Mt. if ( ((SkillsA.filter(e => e.get("name") === 'Beastbane').length > 0) && WeaknessB.includes("Beast")) || ((SkillsA.filter(e => e.get("name") === 'Golembane').length > 0) && WeaknessB.includes("Construct")) || ( StrengthsA.includes("Beast") && WeaknessB.includes("Beast")) || ( StrengthsA.includes("Flier") && WeaknessB.includes("Flier")) || ( StrengthsA.includes("Dragon") && WeaknessB.includes("Dragon")) || ( StrengthsA.includes("Armor") && WeaknessB.includes("Armor")) || ( StrengthsA.includes("Monster") && WeaknessB.includes("Monster")) ){ MtA *= 3; Chatstr += "Attacker has weapon effectiveness! \n"; } if ( ((SkillsB.filter(e => e.get("name") === 'Beastbane').length > 0) && WeaknessA.includes("Beast")) || ((SkillsA.filter(e => e.get("name") === 'Golembane').length > 0) && WeaknessB.includes("Construct")) || ( StrengthsB.includes("Beast") && WeaknessA.includes("Beast")) || ( StrengthsB.includes("Flier") && WeaknessA.includes("Flier")) || ( StrengthsB.includes("Dragon") && WeaknessA.includes("Dragon")) || ( StrengthsB.includes("Armor") && WeaknessA.includes("Armor")) || ( StrengthsB.includes("Monster") && WeaknessA.includes("Monster")) ){ MtB *= 3; Chatstr += "Defender has weapon effectiveness! \n"; } //Targeted stat if ( (PhysWepTypes.includes(WTypeA))||(PhysWeps.includes(WNameA)) ){ DmgtypeA = "Physical"; DmgA = (StrA + MtA) - DefB; } else if ( (MWepTypes.includes(WTypeA))||(MagWeps.includes(WNameA)) ){ DmgtypeA = "Magical"; DmgA = (MagA + MtA) - ResB; } else if (WTypeA == "Firearm/Taneg.") { DmgtypeA = "Firearm"; DmgA = MtA - DefB; } else { DmgtypeA = "Healing"; DmgA = 0; Chatstr += "Unit cannot attack!"; sendChat("System","Unit cannot attack!"); return; } if (DmgA < 0){ DmgA = 0; } DmgA += DmgmodA; //dark magic vs. tome bonuses if ((WTypeA == "Dark Magic") && (MagWeps.includes(WTypeB))){ DmgA += 4 } log(DmgtypeA); log(DmgA); if ( (PhysWepTypes.includes(WTypeB))||(PhysWeps.includes(WNameB)) ){ DmgtypeB = "Physical"; DmgB = (StrB + MtB) - DefA; } else if ( (MWepTypes.includes(WTypeB))||(MagWeps.includes(WNameB)) ){ DmgtypeB = "Magical"; DmgB = (MagB + MtB) - ResA; } else if (WTypeB == "Firearm/Taneg."){ DmgtypeB = "Firearm"; DmgB = MtB - DefA; } else { DmgtypeB = "Healing"; DmgB = 0; //Set damage to 0 so you don't accidentally heal the enemy; CanAttackB = false; } if (DmgB < 0){ DmgB = 0; } DmgB += DmgmodB if ((WTypeB == "Dark Magic") && (MagWeps.includes(WTypeA))){ DmgB += 4 } //check for doubling/braves if ( (SpdA - WtA) - (SpdB - WtB) > 5 || WNameA.toLowerCase().includes("brave")){ DoubleA = true; log("Attacker can double!"); if ( (SpdA - WtA) - (SpdB - WtB) > 5 && WNameA.toLowerCase().includes("brave")){ QuadA = true; log("Attacker can quad!"); } } if ( (SpdB - WtB) - (SpdA - WtA) > 5 || WNameB.toLowerCase().includes("brave")){ DoubleB = true; log("Defender can double!"); if ( (SpdB - WtB) - (SpdA - WtA) > 5 && WNameB.toLowerCase().includes("brave")){ QuadB = true; log("Defender can quad!"); } } //Check for WTA let WIndexA = WepTypes.indexOf(WTypeA)+ 1; let WIndexB = WepTypes.indexOf(WTypeB)+ 1; let WIN = WepTypes.indexOf(WTypeA); let CurrWR = WepRanks[WIN]; let CWRVal = Number(CurrWR.get("current")); //Assume number because it's a numerical input log(CurrWR); log(CWRVal); if( (WIndexA == 1 && WIndexB == 3) || (WIndexA == 3 && WIndexB == 2) || (WIndexA == 2 && WIndexB == 1) || (WIndexA == 4 && WIndexB == 5) || (WIndexA == 5 && WIndexB == 6) || (WIndexA == 6 && WIndexB == 4) || (WIndexA == 7 && WIndexB == 8) || (WIndexA == 8 && WIndexB == 9) || (WIndexA == 9 && WIndexB == 7)) { DmgA +=1; HitA +=15; DmgB -= 1; HitB -=15; Chatstr += "Attacker has WTA! \n"; } if( (WIndexA == 3 && WIndexB == 1) || (WIndexA == 2 && WIndexB == 3) || (WIndexA == 1 && WIndexB == 2) || (WIndexA == 5 && WIndexB == 4) || (WIndexA == 6 && WIndexB == 5) || (WIndexA == 4 && WIndexB == 6) || (WIndexA == 8 && WIndexB == 7) || (WIndexA == 9 && WIndexB == 8) || (WIndexA == 7 && WIndexB == 9)) { DmgA -=1; HitA -=15; DmgB += 1; HitB +=15; Chatstr += "Defender has WTA! \n"; } if (DmgA < 0){ DmgA = 0; } if (DmgB < 0){ DmgB = 0; } if (typeof(UsesA) === "object"){ function DecUsesA() { UsesA.setWithWorker({current: Number(UsesA.get("current")) - 1}); } log("Is an object!"); } else { log("Not an object!"); function DecUsesA() { UsesA -= 1; } } if (typeof(UsesB) === "object"){ function DecUsesB() { UsesB.setWithWorker({current: Number(UsesB.get("current")) - 1}); } log("Is an object!"); } else { log("Not an object!"); function DecUsesB() { UsesB -= 1; } } for (var i in SkillsA){ SkillsA[i] = SkillsA[i].get("action"); if (SkillsA[i] != ""){ SkillsA[i] = JSON.parse(SkillsA[i]) } } log(SkillsA) for (var i in SkillsB){ SkillsB[i] = SkillsB[i].get("action"); if (SkillsB[i] != ""){ SkillsB[i] = JSON.parse(SkillsB[i]) } } log(SkillsB) //Skills system! :^) /*Here is an example of Speedtaker so I don't have to keep checking back to see what I used: { "name": "Speedtaker", "triggertime": "before", "u_wepreq": ["Sword/Katana","Lance/Nagin.","Axe/Club","Bow/Yumi","Dagger/Shurik.","Firearm/Taneg.","Anima Magic","Light Magic","Dark Magic","Stones/Other","Staves/Rods"], "e_wepreq": ["Sword/Katana","Lance/Nagin.","Axe/Club","Bow/Yumi","Dagger/Shurik.","Firearm/Taneg.","Anima Magic","Light Magic","Dark Magic","Stones/Other","Staves/Rods"], "whotriggered": "either", "radius_effect": "none", "physmagcond": false, "killcond": true, "rng": "any", "rngmod": "none", "u_healfactor": 0, "e_healfactor": 0, "u_hitmod": 0, "e_hitmod": 0, "u_critmod": 0, "e_critmod": 0, "u_avomod": 0, "e_avomod": 0, "u_ddgmod": 0, "e_ddgmod": 0, "physmag": false, "u_damagemod": "0", "e_damagemod": "0", "u_stat_target": "Spd", "e_stat_target": "none", "u_stat_targetmod": "2", "e_stat_targetmod": 0, "children_skills": [] } */ //stat initializations- technically, these do nothing in the main function because ~block scope~ let user; let RNGSklU; let RNGLuckU; let CurrHPU; let CurrHPE; let HPU; let HPE; let StrU; let StrE; let MagU; let MagE; let SklU; let SklE; let SpdU; let SpdE; let LckU; let LckE; let DefU; let DefE; let ResU; let ResE; let HitU; let HitE; let CritU; let CritE; let AvoU; let AvoE; let DdgU; let DdgE; let DmgU; let DmgE; let DmgtypeU; let DmgtypeE; let PhysmagU; let PhysmagE; let PhysmaginvU; let PhysmaginvE; let StattargetU; let StattargetE; let Dmg_U; let Dmg_E; let EXPAmod = (10 + ((Math.abs(InLvB-InLvA)*3))); let WEXPA = 2; function Skill(userid,targetid,obj,triggertime) { //haha END ME if (typeof obj != "object"){ log("obj is not an object :(") return; } if ((triggertime == obj.triggertime) && (((obj.whotriggered == "attacker") && (userid == attacker.id)) || ((obj.whotriggered == "defender") && (userid == defender.id)) || (obj.whotriggered == "either"))) { log("Okay, first barrier passed") if ((userid == attacker.id) && (obj.u_wepreq.indexOf(WTypeA) != -1) && (obj.e_wepreq.indexOf(WTypeB) != -1)) { //obj.u_wepreq is a list of weapon types (to account for Aegis/Pavise & other similar skills) //just change "any" to a list of all weapon types, I guess log("Skill user is attacker"); user = "attacker"; RNGSklU = SklA; RNGLckU = LckA; CurrHPU = CurrHPA; CurrHPE = CurrHPB; DmgtypeU = DmgtypeA; DmgtypeE = DmgtypeB; Usertoken = selectedToken; Enemtoken = targetToken; Dmg_U = DmgA; //just for expressions'sake Dmg_E = DmgB; } else if ((userid == defender.id) && (obj.u_wepreq.indexOf(WTypeB) != -1) && (obj.e_wepreq.indexOf(WTypeA) != -1)) { user = "defender"; log("Skill user is defender") RNGSklU = SklB; RNGLckU = LckB; CurrHPU = CurrHPB; CurrHPE = CurrHPA; DmgtypeU = DmgtypeB; DmgtypeE = DmgtypeA; Usertoken = targetToken; Enemtoken = selectedToken; Dmg_U = DmgB; //just for expressions'sake Dmg_E = DmgA; } else { log("You probably don't have the right weapons") return; } log("DamageU is" + Dmg_U); //stat definitions HPU = findObjs({ characterid: userid, name: "HP_bd" })[0]; HPE = findObjs({ characterid: targetid, name: "HP_bd" })[0]; StrU = findObjs({ characterid: userid, name: "Str_bd" })[0]; StrE = findObjs({ characterid: targetid, name: "Str_bd" })[0]; MagU = findObjs({ characterid: userid, name: "Mag_bd" })[0]; MagE = findObjs({ characterid: targetid, name: "Mag_bd" })[0]; SklU = findObjs({ characterid: userid, name: "Skl_bd" })[0]; SklE = findObjs({ characterid: targetid, name: "Skl_bd" })[0]; SpdU = findObjs({ characterid: userid, name: "Spd_bd" })[0]; SpdE = findObjs({ characterid: targetid, name: "Spd_bd" })[0]; LckU = findObjs({ characterid: userid, name: "Lck_bd" })[0]; LckE = findObjs({ characterid: targetid, name: "Lck_bd" })[0]; DefU = findObjs({ characterid: userid, name: "Def_bd" })[0]; DefE = findObjs({ characterid: targetid, name: "Def_bd" })[0]; ResU = findObjs({ characterid: userid, name: "Res_bd" })[0]; ResE = findObjs({ characterid: targetid, name: "Res_bd" })[0]; //nice stat-variables for use in expressions and such let HP_StatU = getAttrByName(userid, 'hp_total'); let HP_StatE = getAttrByName(targetid, 'hp_total'); let HP_CurrU = getAttrByName(userid, 'hp_current'); let HP_CurrE = getAttrByName(targetid, 'hp_current'); let Str_StatU = getAttrByName(userid, 'str_total'); let Str_StatE = getAttrByName(targetid, 'str_total'); let Mag_StatU = getAttrByName(userid, 'mag_total'); let Mag_StatE = getAttrByName(targetid, 'mag_total'); let Skl_StatU = getAttrByName(userid, 'skl_total'); let Skl_StatE = getAttrByName(targetid, 'skl_total'); let Spd_StatU = getAttrByName(userid, 'spd_total'); let Spd_StatE = getAttrByName(targetid, 'spd_total'); let Lck_StatU = getAttrByName(userid, 'lck_total'); let Lck_StatE = getAttrByName(targetid, 'lck_total'); let Def_StatU = getAttrByName(userid, 'def_total'); let Def_StatE = getAttrByName(targetid, 'def_total'); let Res_StatU = getAttrByName(userid, 'res_total'); let Res_StatE = getAttrByName(targetid, 'res_total'); let rng; if (obj.rng == "Skill") { rng = RNGSklU; } if (obj.rng == "Luck") { rng = RNGLckU; } if ((obj.customcond != "none") && (eval(obj.customcond) != true)){ return; } if ((obj.turncond != "none") && (eval(obj.turncond) != true)){ return; } log(obj.rng) //actual skill function function skillMain(){ //PhysmagE if (DmgtypeE == "Physical" || DmgtypeE == "Firearm") { PhysmagE = getAttrByName(targetid, "str_total"); PhysmaginvE = getAttrByName(targetid, "mag_total"); //inv for stuff like Ignis log(targetid) } else { PhysmagE = getAttrByName(targetid, "mag_total"); PhysmaginvE = getAttrByName(targetid, "str_total"); } //I would add a def/res parameter, but I'm just going to be lazy and use the defense AND resistance definition for Luna. log("PhysmagE is " + PhysmagE) //PhysmagU if (DmgtypeU == "Physical" || DmgtypeU == "Firearm") { PhysmagU = getAttrByName(userid, "str_total"); PhysmaginvU = getAttrByName(userid, "mag_total"); log(targetid) } else { PhysmagU = getAttrByName(userid, "mag_total"); PhysmaginvU = getAttrByName(userid, "str_total"); } log("PhysmagU is " + PhysmagU) /* Parse damage and HP modifiers- normally eval() is incredibly dangerous and usually Shouldn't Be Used Under Any Circumstance Ever, but the Roll20 API sandboxes it, so I think it should be alright. Oh well!*/ let DamagemodU = eval(obj.u_damagemod); log("Damage mod is " + DamagemodU) let DamagemodE = eval(obj.e_damagemod); let HealmodU = parseInt(eval(obj.u_healfactor)); let HealmodE = parseInt(eval(obj.e_healfactor)); log("HealmodU is" + HealmodU) let statnames = ["HP", "Str", "Mag", "Skl", "Spd", "Lck", "Def", "Res"]; //determining the actual stat target if (obj.u_stat_target || obj.e_stat_target != "none") { for (var r in statnames) { if (obj.u_stat_target == statnames[r]) { StattargetU = eval(statnames[r] + "U"); } if (obj.e_stat_target == statnames[r]) { StattargetE = eval(statnames[r] + "U"); } } } let StattargetmodU = eval(obj.u_stat_targetmod); let StattargetmodE = eval(obj.e_stat_targetmod); if (obj.u_stat_target != "none"){ StattargetU.setWithWorker({ current: Number(StattargetU.get("current")) + Number(StattargetmodU) }); log("Set targeted stat to "+ StattargetU.get("current")); } if (obj.e_stat_target != "none"){ StattargetE.setWithWorker({ current: Number(StattargetE.get("current")) + Number(StattargetmodE) }); log("Set targeted stat to "+ StattargetE.get("current")); } if (userid == attacker.id) { log("Damage before is " + DmgA) DmgA += DamagemodU; log("Damage after is " + DmgA) DmgB += DamagemodE; HitA += obj.u_hitmod; HitB += obj.e_hitmod; CritA += obj.u_critmod; CritB += obj.e_critmod; AvoA += obj.u_avomod; AvoB += obj.e_avomod; DdgA += obj.u_ddgmod; DdgB += obj.e_ddgmod; HPA = parseInt(HPA) + HealmodU; //this has to be here because sometimes it'll be stupid and overflow if it's not >:( HPB = parseInt(HPB) + HealmodE; EXPAmod *= obj.expmod_u; WEXPA *= obj.wexpmod_u } else { DmgB += DamagemodU; DmgA += DamagemodE; HitB += obj.u_hitmod; HitA += obj.e_hitmod; CritB += obj.u_critmod; CritA += obj.e_critmod; AvoB += obj.u_avomod; AvoA += obj.e_avomod; DdgB += obj.u_ddgmod; DdgA += obj.e_ddgmod; HPB = parseInt(HPB) + HealmodU; HPA = parseInt(HPA) + HealmodE; } log(HPA) if (obj.radius != 0){ //tortured screaming let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(Usertoken,token) > obj.radius || token.get("represents") == Usertoken.get("represents")) return false; else return true; }); log("Tokens in radius are: ") for (var i in tokenInRadius){ log(tokenInRadius[i]) //stat targets let char = tokenInRadius[i].get("represents") let HPcurrC = findObjs({ characterid: char, name: "HP_current"})[0]; let StrC = findObjs({ characterid: char, name: "Str_bd"})[0]; let MagC = findObjs({ characterid: char, name: "Mag_bd"})[0]; let SklC = findObjs({ characterid: char, name: "Skl_bd"})[0]; let SpdC = findObjs({ characterid: char, name: "Spd_bd"})[0]; let LckC = findObjs({ characterid: char, name: "Lck_bd"})[0]; let DefC = findObjs({ characterid: char, name: "Def_bd"})[0]; let ResC = findObjs({ characterid: char, name: "Res_bd"})[0]; let HitC = findObjs({ characterid: char, name: "Hitmod"})[0]; let CritC = findObjs({ characterid: char, name: "Critmod"})[0]; let AvoC = findObjs({ characterid: char, name: "Avomod"})[0]; let DdgC = findObjs({ characterid: char, name: "Ddgmod"})[0]; //numerical stats let HPcurrStat = getAttrByName(char, 'HP_current'); let StrStat = getAttrByName(char, 'Str_total'); let MagStat = getAttrByName(char, 'Mag_total'); let SklStat = getAttrByName(char, 'Skl_total'); let SpdStat = getAttrByName(char, 'Spd_total'); let LckStat = getAttrByName(char, 'Lck_total'); let DefStat = getAttrByName(char, 'Def_total'); let ResStat = getAttrByName(char, 'Res_total'); let HitStat = getAttrByName(char, 'Hit'); let CritStat = getAttrByName(char, 'Crit'); let AvoStat = getAttrByName(char, 'Avo'); let DdgStat = getAttrByName(char, 'Ddg'); effect = eval(obj.radius_effect); //effect MUST be an array!!! rad_effect = Number(effect[0].get("current")) + parseInt(Number(effect[1])) log(effect[0].get("current")) effect[0].setWithWorker({ current: rad_effect }); log(effect[0].get("current")) if ((effect[0] == HPcurrC) && (char == attacker.id)){ HPA += parseInt(effect[1]) } if ((effect[0] == HPcurrC) && (char == defender.id)){ HPB += parseInt(effect[1]) } } } //recursionnn if (obj.children_skills != []){ for (var y in obj.children_skills){ Child_Skill = JSON.parse(obj.children_skills[y]); Skill(userid, targetid, Child_Skill, "any"); //child implementations of preexisting skills should have the triggertime "any" as well } } //Attack multiplier for stuff like Astra if (obj.attack_multiplier != 0){ if (userid == attacker.id){ for (i = 0; i < obj.attack_multiplier; i++){ if (randomInteger(100) < (HitA - AvoB)){ Chatstr += AName + "'s attack hits! \n"; //Check if attack crits if (randomInteger(100) < (CritA - DdgB)){ DmgA *= 3; Chatstr += AName+ " crits! \n"; } //No AOE checking because that's stupidly broken. >:O HPB -= DmgA; log("Damage is " + DmgA); CurrHPB.set("current", HPB); CWRVal += 2; CurrWR.set("current",CWRVal); log("Incremented weapon EXP!"); DecUsesA(); log("Decreased weapon uses!"); } else { Chatstr += AName+ " misses! \n"; } } DoubleA = false; } else { for (i = 0; i < obj.attack_multiplier; i++){ if (randomInteger(100) < (HitB - AvoA)){ Chatstr += DName+ "'s attack hits!"; //Check if attack crits if (randomInteger(100) < (CritB - DdgA)){ DmgB *= 3; Chatstr += "\n"+ DName+ " crits!"; } HPA -= DmgB; CurrHPA.set("current", HPA); //Defender gets no WEXP to discourage turtling on EP DecUsesB(); log("Decreased weapon uses!"); } else { Chatstr += DName+ " misses!"; } } DoubleB = false; } } if (obj.custom_string != ""){ Chatstr += '' + obj.custom_string + "\n" } else { Chatstr += '' + obj.name + " activated!\n" } } //more conditional checks if (obj.e_physmagcond != false){ if ((obj.e_physmagcond == "Physical" && DmgtypeE == "Magical") || (obj.e_physmagcond == "Magical" && DmgtypeE == ("Physical" || "Firearm"))){ return; } } if (obj.u_physmagcond != false){ if ((obj.u_physmagcond == "Physical" && DmgtypeU == "Magical") || (obj.u_physmagcond == "Magical" && DmgtypeU == ("Physical" || "Firearm"))){ return; } } if (obj.killcond == true){ //this should only be true if the triggertime is after if (CurrHPE.get("current") > 0){ return; } } if (obj.rng != "none") { if (randomInteger(100) < (rng * obj.rngmod)) { skillMain(); } else { log("RIP RNG") return; } } else { //Plain ol' skill trigger log("Regular skillmain") skillMain(); } } else { log(triggertime + " vs " + obj.triggertime); log("Attacker id is " + attacker.id + "; Defender id is " + defender.id); log("Userid is" + userid); log("Whotriggered is " + obj.whotriggered); return; }}; //I know it looks weird, but don't touch this! //before triggers for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "before"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "before"); } //Actual battle script //Check if attacker's attack hits/is in range let diff = parseInt(ManhDist(selectedToken, targetToken)); log(diff + " tiles away!"); let css = { attack: 'style = "color: #353535; border = 1px solid #353535;"' }; let diffcheckA; let diffcheckB; log(diff + " " + Range1A); log(diff + " " + Range1B); if (CanAttackA == true) { if ((diff >= Range1A) && (diff <= Range2A)){ log(Range1A + "-"+ Range2A) diffcheckA = true; Chatstr += AName+ "'s attack is in range! \n"; if (randomInteger(100) < (HitA - AvoB)){ Chatstr += AName + "'s attack hits! \n"; //Battle skill trigger for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritA - DdgB)){ DmgA *= 3; Chatstr += AName+ " crits! \n"; } //radius if (AOEA != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(targetToken,token) > AOEA ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgA }); } } HPB -= DmgA; log("Damage is " + DmgA); CurrHPB.set("current", HPB); CWRVal += WEXPA; CurrWR.set("current",CWRVal); log("Incremented weapon EXP!"); DecUsesA(); log("Decreased weapon uses!"); } else { Chatstr += AName+ " misses! \n"; } } else { Chatstr += AName + "'s attack is not in range! \n"; } } else { Chatstr += AName +" cannot attack!\n"; } if (CanAttackB == true){ //Check if defender's attack hits if (((Range1B) <= (diff)) && ((diff) <= (Range2B))){ diffcheckB = true; Chatstr += DName + "'s attack is in range! \n"; if (randomInteger(100) < (HitB - AvoA)){ Chatstr += DName+ "'s attack hits!"; //battle skill trigger for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritB - DdgA)){ DmgB *= 3; Chatstr += "\n"+ DName+ " crits!"; } //radius if (AOEB != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(selectedToken,token) > AOEB ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgB }); } } HPA -= DmgB; CurrHPA.set("current", HPA); //Defender gets no WEXP to discourage turtling on EP DecUsesB(); log("Decreased weapon uses!"); } else { Chatstr += DName+ " misses!"; } } else { Chatstr += DName + "'s attack is not in range!"; } } else { Chatstr += DName +" cannot attack!"; } //Attacker doubles; I don't think I should need to do usability checking for doubleattacking since it's checked within the battle calc if ((DoubleA === true) && (CanAttackA == true) && (diffcheckA == true)){ Chatstr += "\n"+ AName+ " doubleattacks! \n"; if (randomInteger(100) < (HitA - AvoB)){ Chatstr += AName+ "'s attack hits!"; for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritA - DdgB)){ DmgA *= 3; Chatstr += "\n"+ AName+ " crits!"; } //radius if (AOEA != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(targetToken,token) > AOEA ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgA }); } } HPB -= DmgA; CurrHPB.set("current", HPB); CWRVal += WEXPA; CurrWR.set("current",CWRVal); log("Incremented weapon EXP!"); DecUsesA(); log("Decreased weapon uses!"); } else { Chatstr += AName+ " misses!"; } if (QuadA === true){ Chatstr += AName+ " tripleattacks! \n"; if (randomInteger(100) < (HitA - AvoB)){ Chatstr += AName+ "'s attack hits! \n"; for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritA - DdgB)){ DmgA *= 3; Chatstr += AName+ " crits! \n"; } //radius if (AOEA != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(targetToken,token) > AOEA ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgA }); } } HPB -= DmgA; CurrHPB.set("current", HPB); CWRVal += WEXPA; CurrWR.set("current",CWRVal); log("Incremented weapon EXP!"); DecUsesA(); log("Decreased weapon uses!"); } else { Chatstr += AName+ " misses! \n"; } Chatstr += AName+ " quadrupleattacks! \n"; if (randomInteger(100) < (HitA - AvoB)){ Chatstr += AName+ "'s attack hits! \n"; for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritA - DdgB)){ DmgA *= 3; Chatstr += AName+ " crits! \n"; } //radius if (AOEA != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(targetToken,token) > AOEA ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgA }); } } HPB -= DmgA; CurrHPB.set("current", HPB); CWRVal += WEXPA; CurrWR.set("current",CWRVal); log("Incremented weapon EXP!"); DecUsesA(); log("Decreased weapon uses!"); } else { Chatstr += AName+ " misses!"; } } } //Defender doubles if ((DoubleB === true) && (CanAttackB == true) && (diffcheckB == true)){ Chatstr += "\n"+ DName+ " doubleattacks! \n"; if (randomInteger(100) < (HitB - AvoA)){ Chatstr += DName+ "'s attack hits! \n"; for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritB - DdgA)){ DmgB *= 3; Chatstr += DName+ " crits! \n"; } //radius if (AOEB != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(selectedToken,token) > AOEB ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgB }); } } HPA -= DmgB; CurrHPA.set("current", HPA); DecUsesB(); log("Decreased weapon uses!"); } else { Chatstr += DName+ " misses! \n"; } if (QuadB === true){ Chatstr += DName+ " tripleattacks! \n"; if (randomInteger(100) < (HitB - AvoA)){ Chatstr += DName+ "'s attack hits! \n"; for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritB - DdgA)){ DmgB *= 3; Chatstr += DName+ " crits! \n"; } //radius if (AOEB != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(selectedToken,token) > AOEB ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgB }); } } HPA -= DmgB; CurrHPA.set("current", HPA); DecUsesB(); log("Decreased weapon uses!"); } else { Chatstr += DName+ " misses! \n"; } Chatstr += DName+ " quadrupleattacks! \n"; if (randomInteger(100) < (HitB - AvoA)){ Chatstr += DName+ "'s attack hits! \n"; for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "during"); } for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "during"); } //Check if attack crits if (randomInteger(100) < (CritB - DdgA)){ DmgB *= 3; Chatstr += DName+ " crits! \n"; } //radius if (AOEB != 0){ let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(selectedToken,token) > AOEB ) return false; else return true; }); for (i in tokenInRadius){ let char = tokenInRadius[i].get("represents"); let HPchar = findObjs({ characterid: char, name: "HP_current" })[0]; HPchar.setWithWorker({ current: HPchar.get("current") - DmgB }); } } HPA -= DmgB; CurrHPA.set("current", HPA); DecUsesB(); log("Decreased weapon uses!"); } else { Chatstr += DName+ " misses!"; } } } //after triggers for (i in SkillsA){ Skill(attacker.id, defender.id, SkillsA[i], "after"); } for (i in SkillsB){ Skill(defender.id, attacker.id, SkillsB[i], "after"); } sendChat(who,'
'+ Chatstr +'
'); log('
'+ Chatstr +'
'); if (IsPromoA == true){ InLvA += 20; } if (IsPromoB == true){ InLvB += 20; } //Calculate EXP; commented out for the test EXPA += EXPAmod CurrEXP.set("current",EXPA); if (CurrEXP.get("current") >= 100){ CurrEXP.set("current",CurrEXP.get("current")-100); //Get growths LvA.set("current", parseInt(LvA.get("current")) + 1); let Lvstr = "/me leveled up!"; let HPG = Number(getAttrByName(attacker.id, 'hp_gtotal')); let StrG = Number(getAttrByName(attacker.id, 'str_gtotal')); let MagG = Number(getAttrByName(attacker.id, 'mag_gtotal')); let SklG = Number(getAttrByName(attacker.id, 'skl_gtotal')); let SpdG = Number(getAttrByName(attacker.id, 'spd_gtotal')); let LckG = Number(getAttrByName(attacker.id, 'lck_gtotal')); let DefG = Number(getAttrByName(attacker.id, 'def_gtotal')); let ResG = Number(getAttrByName(attacker.id, 'res_gtotal')); let growthslist = [HPG,StrG,MagG,SklG,SpdG,LckG,DefG,ResG]; let HPi = Number(getAttrByName(attacker.id, 'hp_i')); let Stri = Number(getAttrByName(attacker.id, 'str_i')); let Magi = Number(getAttrByName(attacker.id, 'mag_i')); let Skli = Number(getAttrByName(attacker.id, 'skl_i')); let Spdi = Number(getAttrByName(attacker.id, 'spd_i')); let Lcki = Number(getAttrByName(attacker.id, 'lck_i')); let Defi = Number(getAttrByName(attacker.id, 'def_i')); let Resi = Number(getAttrByName(attacker.id, 'res_i')); let sprefix = [HPi,Stri,Magi,Skli,Spdi,Lcki,Defi,Resi]; let HPSG = findObjs({ characterid: attacker.id, name: "HP_i", type: "attribute"})[0]; let StrSG = findObjs({ characterid: attacker.id, name: "Str_i", type: "attribute"})[0]; let MagSG = findObjs({ characterid: attacker.id, name: "Mag_i", type: "attribute"})[0]; let SklSG = findObjs({ characterid: attacker.id, name: "Skl_i", type: "attribute"})[0]; let SpdSG = findObjs({ characterid: attacker.id, name: "Spd_i", type: "attribute"})[0]; let LckSG = findObjs({ characterid: attacker.id, name: "Lck_i", type: "attribute"})[0]; let DefSG = findObjs({ characterid: attacker.id, name: "Def_i", type: "attribute"})[0]; let ResSG = findObjs({ characterid: attacker.id, name: "Res_i", type: "attribute"})[0]; let statslist = [HPSG,StrSG,MagSG,SklSG,SpdSG,LckSG,DefSG,ResSG]; log(statslist); let slist = ["HP","Str","Mag","Skl","Spd","Lck","Def","Res"]; for (var i = 0; i < growthslist.length - 1; i++){ gi = growthslist[i]; log(gi); if (randomInteger(100) < gi){ statslist[i].setWithWorker({current: sprefix[i] + 1}); if (gi > 100){ if (randomInteger(100) < gi){ Lvstr += "\n + 2 to "+ slist[i] + "!"; statslist[i].setWithWorker({current: sprefix[i] + 2}); } else{ Lvstr += "\n + 1 to "+ slist[i] + "!"; } } else { Lvstr += "\n + 1 to "+ slist[i] + "!"; } } } log(Lvstr); sendChat(who,Lvstr); } } //items if (command == 'item') { // Make sure enough parameters were sent, to avoid index out of bounds if (parts.length < 1) { sendChat('SYSTEM', 'You must provide a selected token id.'); return; } // Assume the first two parameters are object IDs var selectedId = parts[0]; var item = parts.slice(1).join(" ") // Attempt to get the objects as graphics var selectedToken = getObj('graphic', selectedId); // If the objects *aren't* graphics, or the parameters weren't IDs, fail gracefully if (!selectedToken) { sendChat('SYSTEM', 'Selected token id not provided.'); return; } // Get a variable to use as the "who" for sendChat var who = getObj('character', selectedToken.get('represents')); if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } if (item == ""){ sendChat("System","No item!") return; } var user = getObj('character', selectedToken.get('represents')); //Personal values, for statboosters let HPi = findObjs({ characterid: user.id, name: "HP_i", type: "attribute"})[0]; let Stri = findObjs({ characterid: user.id, name: "Str_i", type: "attribute"})[0]; let Magi = findObjs({ characterid: user.id, name: "Mag_i", type: "attribute"})[0]; let Skli = findObjs({ characterid: user.id, name: "Skl_i", type: "attribute"})[0]; let Spdi = findObjs({ characterid: user.id, name: "Spd_i", type: "attribute"})[0]; let Lcki = findObjs({ characterid: user.id, name: "Lck_i", type: "attribute"})[0]; let Defi = findObjs({ characterid: user.id, name: "Def_i", type: "attribute"})[0]; let Resi = findObjs({ characterid: user.id, name: "Res_i", type: "attribute"})[0]; //Buff/debuff values, for temp statboosters let HPbd = findObjs({ characterid: user.id, name: "HP_bd", type: "attribute"})[0]; let Strbd = findObjs({ characterid: user.id, name: "Str_bd", type: "attribute"})[0]; let Magbd = findObjs({ characterid: user.id, name: "Mag_bd", type: "attribute"})[0]; let Sklbd = findObjs({ characterid: user.id, name: "Skl_bd", type: "attribute"})[0]; let Spdbd = findObjs({ characterid: user.id, name: "Spd_bd", type: "attribute"})[0]; let Lckbd = findObjs({ characterid: user.id, name: "Lck_bd", type: "attribute"})[0]; let Defbd = findObjs({ characterid: user.id, name: "Def_bd", type: "attribute"})[0]; let Resbd = findObjs({ characterid: user.id, name: "Res_bd", type: "attribute"})[0]; //Current HP, for healing items let HPcurrent = findObjs({ characterid: user.id, name: "HP_current", type: "attribute"})[0]; let Userclass = findObjs({ characterid: user.id, name: "Class", type: "attribute"})[0]; let Item_Name0 = findObjs({ characterid: user.id, name: "item_uses0", type: "attribute"})[0]; let Item_Name1 = findObjs({ characterid: user.id, name: "item_name1", type: "attribute"})[0]; let Item_Name2 = findObjs({ characterid: user.id, name: "item_name2", type: "attribute"})[0]; let Item_Uses0 = findObjs({ characterid: user.id, name: "item_uses0", type: "attribute"})[0]; let Item_Uses1 = findObjs({ characterid: user.id, name: "item_uses1", type: "attribute"})[0]; let Item_Uses2 = findObjs({ characterid: user.id, name: "item_uses2", type: "attribute"})[0]; itemuses = [Item_Uses0,Item_Uses1,Item_Uses2] itemnames = [Item_Name0,Item_Name1,Item_Name2] //All items as objects QnQ //Temp statboosters const Hearty_Cheese = { name: "Hearty Cheese", type: "temp_statbooster", target: HPbd, effect: 2 } const Spicy_Chicken = { name: "Spicy Chicken", type: "temp_statbooster", target: Strbd, effect: 2 } const Sweet_Honey = { name: "Sweet Honey", type: "temp_statbooster", target: Magbd, effect: 2 } const Fresh_Bread = { name: "Fresh Bread", type: "temp_statbooster", target: Sklbd, effect: 2 } const Exotic_Spice = { name: "Exotic Spice", type: "temp_statbooster", target: Spdbd, effect: 2 } const Candy_Die = { name: "Candy Die", type: "temp_statbooster", target: Lckbd, effect: 2 } const Hot_Soup = { name: "Hot Soup", type: "temp_statbooster", target: Defbd, effect: 2 } const Pure_Water = { name: "Pure Water", type: "temp_statbooster", target: Resbd, effect: 2 } //Healing const Vulnerary = { name: "Vulnerary", type: "healing", effect: 10 } const Concoction = { name: "Concoction", type: "healing", effect: 20 } const Elixir = { name: "Elixir", type: "healing", effect: 999 } //Statboosters const Fruit_of_Life = { name: "Fruit of Life", type: "statbooster", target: HPi, effect: 2 } const Soma = { name: "Soma", type: "statbooster", target: Stri, effect: 2 } const Golden_Apple = { name: "Golden Apple", type: "statbooster", target: Magi, effect: 2 } const Nethergranate = { name: "Nethergranate", type: "statbooster", target: Skli, effect: 2 } const Pegasus_Cheese = { name: "Pegasus_Cheese", type: "statbooster", target: Spdi, effect: 2 } const Nectar = { name: "Nectar", type: "statbooster", target: Lcki, effect: 2 } const Ambrosia = { name: "Ambrosia", type: "statbooster", target: Defi, effect: 2 } const Talisman = { name: "Talisman", type: "statbooster", target: Resi, effect: 2 } //Promo items const Orions_Bolt = { name: "Orion's Bolt", type: "seal", target: ["Archer","Apothecary"], promo: true } const Hero_Crest = { name: "Hero_Crest", type: "seal", target: ["Fighter","Mercenary","Myrmidon"], promo: true } const Knight_Crest = { name: "Knight_Crest", type: "seal", target: ["Cavalier","Knight"], promo: true } const Elysian_Whip = { name: "Elysian Whip", type: "seal", target: ["Griffin Rider","Pegasus Knight","Wyvern Rider"], promo: true } const Guiding_Ring = { name: "Guiding Ring", type: "seal", target: ["Anima Mage","Dark Mage","Light Mage","Cleric","Troubadour"], promo: true } const Beastly_Claw = { name: "Beastly Claw", type: "seal", target: ["Laguz","Manakete","Kitsune","Wolfskin"], promo: true } const Ocean_Seal = { name: "Ocean Seal", type: "seal", target: ["Thief","Ninja","Oni Savage","Acrobat"], promo: true } const Medal_of_Honor = { name: "Medal of Honor", type: "seal", target: ["Soldier","Villager","Rifleman"], promo: true } const Heart_Seal = { name: "Heart Seal", type: "seal", target: "all", promo: false } //Misc const Chest_Key = { name: "Chest Key", type: "misc", desc: "Opens chests on adjacent spaces." } const Door_Key = { name: "Door Key", type: "misc", desc: "Opens doors on adjacent spaces." } const Lockpick = { name: "Lockpick", type: "misc", desc: "Opens doors and chests. Usable only by thieves." } const Red_Gem = { name: "Red Gem", type: "misc", desc: "Sells for 2500G." } const Blue_Gem = { name: "Blue Gem", type: "misc", desc: "Sells for 5000G." } const White_Gem = { name: "White Gem", type: "misc", desc: "Sells for 10000G." } itemlist = [Hearty_Cheese,Spicy_Chicken,Sweet_Honey,Fresh_Bread,Exotic_Spice,Candy_Die,Hot_Soup,Pure_Water,Vulnerary,Concoction,Elixir,Fruit_of_Life,Soma,Golden_Apple,Nethergranate,Pegasus_Cheese,Nectar,Ambrosia,Talisman,Orions_Bolt,Hero_Crest,Elysian_Whip,Guiding_Ring,Beastly_Claw,Ocean_Seal,Medal_of_Honor,Heart_Seal,Door_Key,Chest_Key,Lockpick,Red_Gem,Blue_Gem,White_Gem]; //Actual scripts //a-an message handling. Obviously, there are some exceptions because it's based on phonetic vowels, but whatever if (item.toLowerCase()[0] == "a"||item.toLowerCase()[0] == "e"||item.toLowerCase()[0] == "i"||item.toLowerCase()[0] == "o"||item.toLowerCase()[0] == "u"){ sendChat(who, '/me uses an ' + item); } else { sendChat(who, '/me uses a ' + item) } for (var i in itemlist){ if (itemlist[i].name == item){ j = itemlist[i] log(j) //item effects if (j.type == "misc"){ sendChat("System",j.desc) } if (j.type == "temp_statbooster"){ j.target.set("current", Number(j.target.get("current")) + j.effect) } if (j.type == "statbooster"){ j.target.set("current", Number(j.target.get("current")) + j.effect) } if (j.type == "healing"){ HPcurrent.set("current", Number(HPcurrent.get("current")) + j.effect) } if (j.type == "seal"){ if (j.promo == true){ if (j.target.indexOf(Userclass.get("current")) != -1 ){ sendChat("System", user.get("name") + " promotes with the " + j.name + "!") } else { sendChat("System", "Cannot promote!") } } else { sendChat("System", user.get("name") + " changes class with a Heart Seal!") } } } } } //staves if (command == 'staff') { if (parts.length < 2) { sendChat('SYSTEM', 'You must provide a selected token id and a target token id.'); return; } var selectedId = parts[0]; var targetId = parts[1]; // Grab tokens var selectedToken = getObj('graphic', selectedId); var targetToken = getObj('graphic', targetId); // Check if the objects aren't tokens or if the passed parameters aren't ids if (!selectedToken) { sendChat('SYSTEM', 'Selected token id not provided.'); return; } if (!targetToken) { sendChat('SYSTEM', 'Target token id not provided.'); return; } // Get a variable to use as the "who" for sendChat var who = getObj('character', selectedToken.get('represents')); if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } var staffer = getObj('character', selectedToken.get('represents')); var target = getObj('character', targetToken.get('represents')); let CurrHPA = findObjs({ characterid: staffer.id, name: "HP_current"})[0]; //Target stats for tasty statuses let CurrHPB = findObjs({ characterid: target.id, name: "HP_current"})[0]; let MaxHPB = findObjs({ characterid: target.id, name: "HP_total"})[0]; let StrB = findObjs({ characterid: target.id, name: "Str_total"})[0]; let MagB = findObjs({ characterid: target.id, name: "Mag_total"})[0]; let SklB = findObjs({ characterid: target.id, name: "Skl_total"})[0]; let SpdB = findObjs({ characterid: target.id, name: "Spd_total"})[0]; let LckB = findObjs({ characterid: target.id, name: "Lck_total"})[0]; let DefB = findObjs({ characterid: target.id, name: "Def_total"})[0]; let ResB = findObjs({ characterid: target.id, name: "Res_total"})[0]; let MovB = findObjs({ characterid: target.id, name: "Mov_total"})[0]; let HPbd = findObjs({ characterid: target.id, name: "HP_bd"})[0]; let Strbd = findObjs({ characterid: target.id, name: "Str_bd"})[0]; let Magbd = findObjs({ characterid: target.id, name: "Mag_bd"})[0]; let Sklbd = findObjs({ characterid: target.id, name: "Skl_bd"})[0]; let Spdbd = findObjs({ characterid: target.id, name: "Spd_bd"})[0]; let Lckbd = findObjs({ characterid: target.id, name: "Lck_bd"})[0]; let Defbd = findObjs({ characterid: target.id, name: "Def_bd"})[0]; let Resbd = findObjs({ characterid: target.id, name: "Res_bd"})[0]; let Movbd = findObjs({ characterid: target.id, name: "Mov_bd"})[0]; //Weapons and h/c/a let HitA = getAttrByName(staffer.id, 'hit'); let AvoB = getAttrByName(target.id, 'avo'); let MagA = getAttrByName(staffer.id, 'mag_total'); let WNameA = getAttrByName(staffer.id, 'repeating_weapons_$0_WName') || "Empty"; let WTypeA = getAttrByName(staffer.id, 'repeating_weapons_$0_WType') || "Stones/Other"; let MtA = parseInt(getAttrByName(staffer.id, 'repeating_weapons_$0_Mt')) || 0; let WtA = parseInt(getAttrByName(staffer.id, 'repeating_weapons_$0_Wt')) || 0; let Range1A = parseInt(getAttrByName(staffer.id, 'repeating_weapons_$0_Range1')) || 1; let Range2A = parseInt(getAttrByName(staffer.id, 'repeating_weapons_$0_Range2')) || 1; let fIDA = getAttrByName(staffer.id, 'fid')|| "" let UsesA = findObjs({ characterid: staffer.id, name: "repeating_weapons_"+fIDA+"_Uses"},{ caseInsensitive: true })[0]; //assumes it exists, since that's a requirement for the thing to activate let diff = ManhDist(selectedToken, targetToken); chatstr = "/me uses " + WNameA + "!" const Heal = { name : "Heal", type : "healing", effect : 10 + (Math.round(MagA/3)) }; const Mend = { name : "Mend", type : "healing", effect : 20 + (Math.round(MagA/3)) }; const Physic = { name : "Physic", type : "healing", effect : 7 + (Math.round(MagA/3)) }; const Recover = { name : "Recover", type : "healing", effect : 35 + (Math.round(MagA/3)) }; const Fortify = { name : "Fortify", type : "healing", effect : 7 + (Math.round(MagA/3)) }; const Bloom_Festal = { name : "Bloom Festal", type : "healing", effect : 7 + (Math.round(MagA/3)) }; const Sun_Festal = { name : "Sun Festal", type : "healing", effect : 14 + (Math.round(MagA/3)) }; const Wane_Festal = { name : "Wane Festal", type : "healing", effect : 2 + (Math.round(MagA/3)) }; const Moon_Festal = { name : "Moon Festal", type : "healing", effect : 25 + (Math.round(MagA/3)) }; const Great_Festal = { name : "Great Festal", type : "healing", effect : 2 + (Math.round(MagA/3)) }; const Freeze = { name : "Freeze", type : "status", target: [Movbd], effect : Number(MovB.get("current")) * -1, status: {status_tread: true}, chatmsg: targetToken.get("name") + " is unable to move this turn!" }; const Enfeeble = { name : "Enfeeble", type : "status", target: [Strbd,Magbd,Sklbd,Spdbd,Lckbd,Defbd,Resbd], effect : -4, status: {"status_back-pain": 4}, chatmsg: targetToken.get("name") + " is enfeebled! -4 to every stat (decreases by 1 each turn)" }; const Entrap = { name : "Entrap", type : "status", target: [Movbd], effect : 0, status: {"status_grab": false}, chatmsg: targetToken.get("name") + " is moved next to the enemy!" }; const Rescue = { name : "Rescue", type : "status", target: [Movbd], effect : 0, status: {"status_grab": false}, chatmsg: targetToken.get("name") + " is rescued!" }; const Silence = { name : "Silence", type : "status", target: [Magbd], effect : Number(MagB.get("current")) * -1, status: {status_interdiction: true}, chatmsg: targetToken.get("name") + " cannot use magic for the next turn!" }; const Hexing_Rod = { name : "Hexing Rod", type : "status", target: [HPbd], effect : Math.round(Number(MaxHPB.get("current")) * -0.5), status: {"status_broken-heart": true}, chatmsg: targetToken.get("name") + "'s HP was halved!" }; //Okay, Skills system time!! let user; let RNGSklU; let RNGLuckU; let CurrHPU; let CurrHPE; let HPU; let HPE; let StrU; let StrE; let MagU; let MagE; let SklU; let SklE; let SpdU; let SpdE; let LckU; let LckE; let DefU; let DefE; let ResU; let ResE; let HitU; let HitE; let CritU; let CritE; let AvoU; let AvoE; let DdgU; let DdgE; let DmgU; let DmgE; let DmgtypeU; let DmgtypeE; let PhysmagU; let PhysmagE; let PhysmaginvU; let PhysmaginvE; let StattargetU; let StattargetE; let CurrEXP = findObjs({ characterid: staffer.id, name: "EXP"})[0]; let LvA = findObjs({ characterid: staffer.id, name: "Level"})[0]; let InLvA = Number(LvA.get("current")); let LvB = findObjs({ characterid: target.id, name: "Level"})[0]; let InLvB = Number(LvB.get("current")); let EXPA = Number(CurrEXP.get("current")); let IsPromoA = getAttrByName(staffer.id, 'isPromo'); let IsPromoB = getAttrByName(target.id, 'isPromo'); let EXPAmod = (10 + ((Math.abs(InLvB-InLvA)*3))); let HPA = Number(getAttrByName(staffer.id, 'hp_current')); let HPB = Number(getAttrByName(target.id, 'hp_current')); function Skill(userid, targetid, obj, triggertime) { //haha END ME if (typeof obj != "object") { log("obj is not an object :(") return; } if (obj.triggertime != "staff"){ return; } //no whotriggered checking because it'll always be the staffer log("Okay, first barrier passed") user = "staffer"; RNGSklU = Number(getAttrByName(staffer.id, 'skl_total')); RNGLckU = Number(getAttrByName(staffer.id, 'lck_total')); CurrHPU = findObjs({ characterid: staffer.id, name: "HP_current" })[0]; CurrHPE = findObjs({ characterid: target.id, name: "HP_current" })[0]; DmgtypeU = "" DmgtypeE = "" //doesn't matter since commands are non-combative anyways Usertoken = selectedToken; //stat definitions HPU = findObjs({ characterid: userid, name: "HP_bd" })[0]; HPE = findObjs({ characterid: targetid, name: "HP_bd" })[0]; StrU = findObjs({ characterid: userid, name: "Str_bd" })[0]; StrE = findObjs({ characterid: targetid, name: "Str_bd" })[0]; MagU = findObjs({ characterid: userid, name: "Mag_bd" })[0]; MagE = findObjs({ characterid: targetid, name: "Mag_bd" })[0]; SklU = findObjs({ characterid: userid, name: "Skl_bd" })[0]; SklE = findObjs({ characterid: targetid, name: "Skl_bd" })[0]; SpdU = findObjs({ characterid: userid, name: "Spd_bd" })[0]; SpdE = findObjs({ characterid: targetid, name: "Spd_bd" })[0]; LckU = findObjs({ characterid: userid, name: "Lck_bd" })[0]; LckE = findObjs({ characterid: targetid, name: "Lck_bd" })[0]; DefU = findObjs({ characterid: userid, name: "Def_bd" })[0]; DefE = findObjs({ characterid: targetid, name: "Def_bd" })[0]; ResU = findObjs({ characterid: userid, name: "Res_bd" })[0]; ResE = findObjs({ characterid: targetid, name: "Res_bd" })[0]; //nice stat-variables for use in expressions and such let HP_StatU = getAttrByName(userid, 'hp_total'); let HP_StatE = getAttrByName(targetid, 'hp_total'); let HP_CurrU = getAttrByName(userid, 'hp_current'); let HP_CurrE = getAttrByName(targetid, 'hp_current'); let Str_StatU = getAttrByName(userid, 'str_total'); let Str_StatE = getAttrByName(targetid, 'str_total'); let Mag_StatU = getAttrByName(userid, 'mag_total'); let Mag_StatE = getAttrByName(targetid, 'mag_total'); let Skl_StatU = getAttrByName(userid, 'skl_total'); let Skl_StatE = getAttrByName(targetid, 'skl_total'); let Spd_StatU = getAttrByName(userid, 'spd_total'); let Spd_StatE = getAttrByName(targetid, 'spd_total'); let Lck_StatU = getAttrByName(userid, 'lck_total'); let Lck_StatE = getAttrByName(targetid, 'lck_total'); let Def_StatU = getAttrByName(userid, 'def_total'); let Def_StatE = getAttrByName(targetid, 'def_total'); let Res_StatU = getAttrByName(userid, 'res_total'); let Res_StatE = getAttrByName(targetid, 'res_total'); let rng; if (obj.rng == "Skill") { rng = RNGSklU; } if (obj.rng == "Luck") { rng = RNGLckU; } if ((obj.customcond != "none") && (eval(obj.customcond) != true)) { return; } if ((obj.turncond != "none") && (eval(obj.turncond) != true)){ return; } log(obj.rng) //actual skill function function skillMain() { //No Physmag :O /* Parse damage and HP modifiers- normally eval() is incredibly dangerous and usually Shouldn't Be Used Under Any Circumstance Ever, but the Roll20 API sandboxes it, so I think it should be alright. Oh well!*/ let HealmodU = parseInt(eval(obj.u_healfactor)); let HealmodE = parseInt(eval(obj.e_healfactor)); log("HealmodU is" + HealmodU) let statnames = ["HP", "Str", "Mag", "Skl", "Spd", "Lck", "Def", "Res"]; //determining the actual stat target if (obj.u_stat_target || obj.e_stat_target != "none") { for (var r in statnames) { if (obj.u_stat_target == statnames[r]) { StattargetU = eval(statnames[r] + "U"); } if (obj.e_stat_target == statnames[r]) { StattargetE = eval(statnames[r] + "U"); } } } let StattargetmodU = eval(obj.u_stat_targetmod); let StattargetmodE = eval(obj.e_stat_targetmod); if (obj.u_stat_target != "none") { StattargetU.setWithWorker({ current: Number(StattargetU.get("current")) + Number(StattargetmodU) }); log("Set targeted stat to " + StattargetU.get("current")); } if (obj.e_stat_target != "none") { StattargetE.setWithWorker({ current: Number(StattargetE.get("current")) + Number(StattargetmodE) }); log("Set targeted stat to " + StattargetE.get("current")); } HPA = parseInt(HPA) + HealmodU; //this has to be here because sometimes it'll be stupid and overflow if it's not >:( HPVal = parseInt(HPVal) + HealmodE; EXPAmod *= obj.expmod_u; log(HPA) if (obj.radius != 0) { //tortured screaming let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(Usertoken, token) > obj.radius || token.get("represents") == Usertoken.get("represents")) return false; else return true; }); log("Tokens in radius are: ") for (var i in tokenInRadius) { log(tokenInRadius[i]) //stat targets let char = tokenInRadius[i].get("represents") let HPcurrC = findObjs({ characterid: char, name: "HP_current" })[0]; let StrC = findObjs({ characterid: char, name: "Str_bd" })[0]; let MagC = findObjs({ characterid: char, name: "Mag_bd" })[0]; let SklC = findObjs({ characterid: char, name: "Skl_bd" })[0]; let SpdC = findObjs({ characterid: char, name: "Spd_bd" })[0]; let LckC = findObjs({ characterid: char, name: "Lck_bd" })[0]; let DefC = findObjs({ characterid: char, name: "Def_bd" })[0]; let ResC = findObjs({ characterid: char, name: "Res_bd" })[0]; let HitC = findObjs({ characterid: char, name: "Hitmod" })[0]; let CritC = findObjs({ characterid: char, name: "Critmod" })[0]; let AvoC = findObjs({ characterid: char, name: "Avomod" })[0]; let DdgC = findObjs({ characterid: char, name: "Ddgmod" })[0]; //numerical stats let HPcurrStat = getAttrByName(char, 'HP_current'); let StrStat = getAttrByName(char, 'Str_total'); let MagStat = getAttrByName(char, 'Mag_total'); let SklStat = getAttrByName(char, 'Skl_total'); let SpdStat = getAttrByName(char, 'Spd_total'); let LckStat = getAttrByName(char, 'Lck_total'); let DefStat = getAttrByName(char, 'Def_total'); let ResStat = getAttrByName(char, 'Res_total'); let HitStat = getAttrByName(char, 'Hit'); let CritStat = getAttrByName(char, 'Crit'); let AvoStat = getAttrByName(char, 'Avo'); let DdgStat = getAttrByName(char, 'Ddg'); let effect = eval(obj.radius_effect); //effect MUST be an array!!! let rad_effect = Number(effect[0].get("current")) + parseInt(Number(effect[1])) log(effect[0].get("current")) effect[0].setWithWorker({ current: rad_effect }); log(effect[0].get("current")) if ((effect[0] == HPcurrC) && (char == staffer.id)) { HPA += parseInt(effect[1]) } if ((effect[0] == HPcurrC) && (char == target.id)) { HPVal += parseInt(effect[1]) } } } CurrHPA.setWithWorker({ current: HPA }); //recursionnn if (obj.children_skills != []) { for (var y in obj.children_skills) { let Child_Skill = JSON.parse(obj.children_skills[y]); Skill(userid, targetid, Child_Skill, "any"); //child implementations of preexisting skills should have the triggertime "any" as well } } if (obj.custom_string != "") { chatstr += '\n' + obj.custom_string + "\n" } else { chatstr += '\n' + obj.name + " activated!\n" } } if (obj.rng != "none") { if (randomInteger(100) < (rng * obj.rngmod)) { skillMain(); } else { log("RIP RNG") return; } } else { //Plain ol' skill trigger log("Regular skillmain") skillMain(); } } let SkillsA = findObjs({ characterid: staffer.id, type: "ability"}); for (var i in SkillsA){ SkillsA[i] = SkillsA[i].get("action"); if (SkillsA[i] != ""){ SkillsA[i] = JSON.parse(SkillsA[i]); } } let temp = [] SkillsA.forEach(function(entry, i) { if (SkillsA[i].triggertime == "staff"){ temp.push(SkillsA[i]) } }); SkillsA = temp; log(SkillsA); const staveslist = [Heal,Mend,Physic,Recover,Fortify,Bloom_Festal,Sun_Festal,Wane_Festal,Moon_Festal,Great_Festal,Freeze,Enfeeble,Entrap,Rescue,Silence,Hexing_Rod]; //Script stuff here if (WTypeA != "Staves/Rods"){ chatstr += "\n Weapon is not a staff!" } else { for (var i in staveslist){ if (staveslist[i].name === WNameA){ j = staveslist[i]; //check for range if (((Range1A) <= (diff)) && ((diff) <= (Range2A))){ if (j.type === "healing"){ //Set with workers in respect to total caps HPVal = j.effect for (var z in SkillsA){ Skill(staffer, target, SkillsA[z], "staff") } CurrHPB.setWithWorker({current: parseInt(CurrHPB.get("current")) + HPVal}) chatstr += "\n" + targetToken.get("name") + " is healed for " + String(HPVal) + " HP!" UsesA.setWithWorker({current: parseInt(UsesA.get("current")) - 1}) } if (j.type === "status"){ //Check for RNG if (randomInteger(100) < (HitA - AvoB)){ for (var a in j.target){ log(j.effect); log(j.target[a]) j.target[a].setWithWorker("current",j.effect) } log(j.status); targetToken.set(j.status); UsesA.setWithWorker({current: parseInt(UsesA.get("current")) - 1}) chatstr += "\n"+ j.chatmsg } else { chatstr += "\n Staff misses!" } } } else { chatstr += "\n Staff is not in range!" } } } } sendChat(who, chatstr); } if (command == 'stats') { if (parts.length < 1) { sendChat('SYSTEM', 'You must provide a selected token id'); return; } if (parts.length < 4) { sendChat('SYSTEM', 'You must provide arguments for all four stats'); return; } // Only one token for this one var selectedId = parts[0]; var hit = Number(parts[1]); var crit = Number(parts[2]); var avo = Number(parts[3]); var ddg = Number(parts[4]); var dmg = Number(parts[5]); log(parts) var selectedToken = getObj('graphic', selectedId); if (!selectedToken) { sendChat('SYSTEM', 'Selected token id not provided.'); return; } var who = getObj('character', selectedToken.get('represents')); var user = who.id if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } let Hitmod = findObjs({ characterid: user, name: "Hitmod"})[0]; log(Hitmod) let Critmod = findObjs({ characterid: user, name: "Critmod"})[0]; log(Critmod) let Avomod = findObjs({ characterid: user, name: "Avomod"})[0]; log(Avomod) let Ddgmod = findObjs({ characterid: user, name: "Ddgmod"})[0]; log(Ddgmod) let Dmgmod = findObjs({ characterid: user, name: "Dmgmod"})[0]; log(Dmgmod) Hitmod.setWithWorker({ current: Number(Hitmod.get("current")) + hit }); Critmod.setWithWorker({ current: Number(Critmod.get("current")) + crit }); Avomod.setWithWorker({ current: Number(Avomod.get("current")) + avo }); Ddgmod.setWithWorker({ current: Number(Hitmod.get("current")) + ddg }); Dmgmod.setWithWorker({ current: Number(Hitmod.get("current")) + dmg }); sendChat(who, "Stats modified!"); } //command1 if (command == 'skill') { if (parts.length < 2) { sendChat('SYSTEM', 'You must provide a selected token id and a target token id.'); return; } var selectedId = parts[0]; var targetId = parts[1]; // Grab tokens var selectedToken = getObj('graphic', selectedId); var targetToken = getObj('graphic', targetId); // Check if the objects aren't tokens or if the passed parameters aren't ids if (!selectedToken) { sendChat('SYSTEM', 'Selected token id not provided.'); return; } if (!targetToken) { sendChat('SYSTEM', 'Target token id not provided.'); return; } // Get a variable to use as the "who" for sendChat var who = getObj('character', selectedToken.get('represents')); if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } //script!! var attacker = getObj('character', selectedToken.get('represents')); var defender = getObj('character', targetToken.get('represents')); //grab all commands let SkillsA = findObjs({ characterid: attacker.id, type: "ability"}); for (var i in SkillsA){ SkillsA[i] = SkillsA[i].get("action"); if (SkillsA[i] != ""){ SkillsA[i] = JSON.parse(SkillsA[i]); } } let temp = [] SkillsA.forEach(function(entry, i) { if (SkillsA[i].triggertime == "command"){ temp.push(SkillsA[i]) } }); SkillsA = temp; let namestr = ""; for (i in SkillsA){ namestr += "|" + SkillsA[i].name; } //SkillsB doesn't exist because they're not selecting anything lol sendChat("System","[Pick Ability](!&#"+"13;!co ?{Pick a skill"+namestr+"} " + selectedId + " " + targetId + ")"); //get second message } //command2 if (command == 'co'){ log("YE") log(parts); var skillName = parts[0]; var selectedId = parts[1]; var targetId = parts[2]; var selectedToken = getObj('graphic', selectedId); var targetToken = getObj('graphic', targetId); var attacker = getObj('character', selectedToken.get('represents')); var defender = getObj('character', targetToken.get('represents')); var who = getObj('character', selectedToken.get('represents')); if (!who) { who = selectedToken.get('name'); } else { who = 'character|' + who.id; } let newSkill = findObjs({ characterid: attacker.id, type: "ability", name: skillName })[0]; log(newSkill) if (newSkill == [] || newSkill == undefined){ sendChat("SYSTEM","Provided skill name does not exist! ") return; } newSkill = newSkill.get("action") let selectedSkill = JSON.parse(newSkill); log(selectedSkill) //Skills system time!! let user; let RNGSklU; let RNGLuckU; let CurrHPU; let CurrHPE; let HPU; let HPE; let StrU; let StrE; let MagU; let MagE; let SklU; let SklE; let SpdU; let SpdE; let LckU; let LckE; let DefU; let DefE; let ResU; let ResE; let HitU; let HitE; let CritU; let CritE; let AvoU; let AvoE; let DdgU; let DdgE; let DmgU; let DmgE; let DmgtypeU; let DmgtypeE; let PhysmagU; let PhysmagE; let PhysmaginvU; let PhysmaginvE; let StattargetU; let StattargetE; let CurrEXP = findObjs({ characterid: attacker.id, name: "EXP"})[0]; let LvA = findObjs({ characterid: attacker.id, name: "Level"})[0]; let InLvA = Number(LvA.get("current")); let LvB = findObjs({ characterid: defender.id, name: "Level"})[0]; let InLvB = Number(LvB.get("current")); let EXPA = Number(CurrEXP.get("current")); let IsPromoA = getAttrByName(attacker.id, 'isPromo'); let IsPromoB = getAttrByName(defender.id, 'isPromo'); let EXPAmod = (10 + ((Math.abs(InLvB-InLvA)*3))); let HPA = Number(getAttrByName(attacker.id, 'hp_current')); let HPB = Number(getAttrByName(defender.id, 'hp_current')); let CurrHPA = findObjs({ characterid: attacker.id, name: "HP_current"})[0]; let CurrHPB = findObjs({ characterid: defender.id, name: "HP_current"})[0]; function Skill(userid, targetid, obj, triggertime) { //haha END ME if (typeof obj != "object") { log("obj is not an object :(") return; } if (obj.triggertime != "command"){ return; } //no whotriggered checking because it'll always be the attacker log("Okay, first barrier passed") user = "attacker"; RNGSklU = Number(getAttrByName(attacker.id, 'skl_total')); RNGLckU = Number(getAttrByName(attacker.id, 'lck_total')); CurrHPU = findObjs({ characterid: attacker.id, name: "HP_current" })[0]; CurrHPE = findObjs({ characterid: defender.id, name: "HP_current" })[0]; DmgtypeU = "" DmgtypeE = "" //doesn't matter since commands are non-combative anyways Usertoken = selectedToken; //stat definitions HPU = findObjs({ characterid: userid, name: "HP_bd" })[0]; HPE = findObjs({ characterid: targetid, name: "HP_bd" })[0]; StrU = findObjs({ characterid: userid, name: "Str_bd" })[0]; StrE = findObjs({ characterid: targetid, name: "Str_bd" })[0]; MagU = findObjs({ characterid: userid, name: "Mag_bd" })[0]; MagE = findObjs({ characterid: targetid, name: "Mag_bd" })[0]; SklU = findObjs({ characterid: userid, name: "Skl_bd" })[0]; SklE = findObjs({ characterid: targetid, name: "Skl_bd" })[0]; SpdU = findObjs({ characterid: userid, name: "Spd_bd" })[0]; SpdE = findObjs({ characterid: targetid, name: "Spd_bd" })[0]; LckU = findObjs({ characterid: userid, name: "Lck_bd" })[0]; LckE = findObjs({ characterid: targetid, name: "Lck_bd" })[0]; DefU = findObjs({ characterid: userid, name: "Def_bd" })[0]; DefE = findObjs({ characterid: targetid, name: "Def_bd" })[0]; ResU = findObjs({ characterid: userid, name: "Res_bd" })[0]; ResE = findObjs({ characterid: targetid, name: "Res_bd" })[0]; //nice stat-variables for use in expressions and such let HP_StatU = getAttrByName(userid, 'hp_total'); let HP_StatE = getAttrByName(targetid, 'hp_total'); let HP_CurrU = getAttrByName(userid, 'hp_current'); let HP_CurrE = getAttrByName(targetid, 'hp_current'); let Str_StatU = getAttrByName(userid, 'str_total'); let Str_StatE = getAttrByName(targetid, 'str_total'); let Mag_StatU = getAttrByName(userid, 'mag_total'); let Mag_StatE = getAttrByName(targetid, 'mag_total'); let Skl_StatU = getAttrByName(userid, 'skl_total'); let Skl_StatE = getAttrByName(targetid, 'skl_total'); let Spd_StatU = getAttrByName(userid, 'spd_total'); let Spd_StatE = getAttrByName(targetid, 'spd_total'); let Lck_StatU = getAttrByName(userid, 'lck_total'); let Lck_StatE = getAttrByName(targetid, 'lck_total'); let Def_StatU = getAttrByName(userid, 'def_total'); let Def_StatE = getAttrByName(targetid, 'def_total'); let Res_StatU = getAttrByName(userid, 'res_total'); let Res_StatE = getAttrByName(targetid, 'res_total'); let rng; if (obj.rng == "Skill") { rng = RNGSklU; } if (obj.rng == "Luck") { rng = RNGLckU; } if ((obj.customcond != "none") && (eval(obj.customcond) != true)) { return; } if ((obj.turncond != "none") && (eval(obj.turncond) != true)){ return; } log(obj.rng) //actual skill function function skillMain() { //No Physmag :O /* Parse damage and HP modifiers- normally eval() is incredibly dangerous and usually Shouldn't Be Used Under Any Circumstance Ever, but the Roll20 API sandboxes it, so I think it should be alright. Oh well!*/ let HealmodU = parseInt(eval(obj.u_healfactor)); let HealmodE = parseInt(eval(obj.e_healfactor)); log("HealmodU is" + HealmodU) let statnames = ["HP", "Str", "Mag", "Skl", "Spd", "Lck", "Def", "Res"]; //determining the actual stat target if (obj.u_stat_target || obj.e_stat_target != "none") { for (var r in statnames) { if (obj.u_stat_target == statnames[r]) { StattargetU = eval(statnames[r] + "U"); } if (obj.e_stat_target == statnames[r]) { StattargetE = eval(statnames[r] + "U"); } } } let StattargetmodU = eval(obj.u_stat_targetmod); let StattargetmodE = eval(obj.e_stat_targetmod); if (obj.u_stat_target != "none") { StattargetU.setWithWorker({ current: Number(StattargetU.get("current")) + Number(StattargetmodU) }); log("Set targeted stat to " + StattargetU.get("current")); } if (obj.e_stat_target != "none") { StattargetE.setWithWorker({ current: Number(StattargetE.get("current")) + Number(StattargetmodE) }); log("Set targeted stat to " + StattargetE.get("current")); } HPA = parseInt(HPA) + HealmodU; //this has to be here because sometimes it'll be stupid and overflow if it's not >:( HPB = parseInt(HPB) + HealmodE; EXPAmod *= obj.expmod_u; log(HPA) if (obj.radius != 0) { //tortured screaming let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(Usertoken, token) > obj.radius || token.get("represents") == Usertoken.get("represents")) return false; else return true; }); log("Tokens in radius are: ") for (var i in tokenInRadius) { log(tokenInRadius[i]) //stat targets let char = tokenInRadius[i].get("represents") let HPcurrC = findObjs({ characterid: char, name: "HP_current" })[0]; let StrC = findObjs({ characterid: char, name: "Str_bd" })[0]; let MagC = findObjs({ characterid: char, name: "Mag_bd" })[0]; let SklC = findObjs({ characterid: char, name: "Skl_bd" })[0]; let SpdC = findObjs({ characterid: char, name: "Spd_bd" })[0]; let LckC = findObjs({ characterid: char, name: "Lck_bd" })[0]; let DefC = findObjs({ characterid: char, name: "Def_bd" })[0]; let ResC = findObjs({ characterid: char, name: "Res_bd" })[0]; let HitC = findObjs({ characterid: char, name: "Hitmod" })[0]; let CritC = findObjs({ characterid: char, name: "Critmod" })[0]; let AvoC = findObjs({ characterid: char, name: "Avomod" })[0]; let DdgC = findObjs({ characterid: char, name: "Ddgmod" })[0]; //numerical stats let HPcurrStat = getAttrByName(char, 'HP_current'); let StrStat = getAttrByName(char, 'Str_total'); let MagStat = getAttrByName(char, 'Mag_total'); let SklStat = getAttrByName(char, 'Skl_total'); let SpdStat = getAttrByName(char, 'Spd_total'); let LckStat = getAttrByName(char, 'Lck_total'); let DefStat = getAttrByName(char, 'Def_total'); let ResStat = getAttrByName(char, 'Res_total'); let HitStat = getAttrByName(char, 'Hit'); let CritStat = getAttrByName(char, 'Crit'); let AvoStat = getAttrByName(char, 'Avo'); let DdgStat = getAttrByName(char, 'Ddg'); let effect = eval(obj.radius_effect); //effect MUST be an array!!! let rad_effect = Number(effect[0].get("current")) + parseInt(Number(effect[1])) log(effect[0].get("current")) effect[0].setWithWorker({ current: rad_effect }); log(effect[0].get("current")) if ((effect[0] == HPcurrC) && (char == attacker.id)) { HPA += parseInt(effect[1]) } if ((effect[0] == HPcurrC) && (char == defender.id)) { HPB += parseInt(effect[1]) } } CurrHPA.setWithWorker({ current: HPA }); CurrHPB.setWithWorker({ current: HPB }); } //recursionnn if (obj.children_skills != []) { for (var y in obj.children_skills) { let Child_Skill = JSON.parse(obj.children_skills[y]); Skill(userid, targetid, Child_Skill, "any"); //child implementations of preexisting skills should have the triggertime "any" as well } } let Chatstr; if (obj.custom_string != "") { Chatstr = '' + obj.custom_string + "\n" } else { Chatstr = ''+attacker.get("name") + " used " + obj.name + "!\n" } sendChat(who, Chatstr); } if (obj.rng != "none") { if (randomInteger(100) < (rng * obj.rngmod)) { skillMain(); } else { log("RIP RNG") return; } } else { //Plain ol' skill trigger log("Regular skillmain") skillMain(); } } Skill(attacker.id, defender.id, selectedSkill, "command") //EXPPPPP EXPA += EXPAmod CurrEXP.set("current",EXPA); if (CurrEXP.get("current") >= 100){ CurrEXP.set("current",CurrEXP.get("current")-100); //Get growths LvA.set("current", Number(LvA.get("current")) + 1); let Lvstr = "/me leveled up!"; let HPG = Number(getAttrByName(attacker.id, 'hp_gtotal')); let StrG = Number(getAttrByName(attacker.id, 'str_gtotal')); let MagG = Number(getAttrByName(attacker.id, 'mag_gtotal')); let SklG = Number(getAttrByName(attacker.id, 'skl_gtotal')); let SpdG = Number(getAttrByName(attacker.id, 'spd_gtotal')); let LckG = Number(getAttrByName(attacker.id, 'lck_gtotal')); let DefG = Number(getAttrByName(attacker.id, 'def_gtotal')); let ResG = Number(getAttrByName(attacker.id, 'res_gtotal')); let growthslist = [HPG,StrG,MagG,SklG,SpdG,LckG,DefG,ResG]; let HPi = Number(getAttrByName(attacker.id, 'hp_i')); let Stri = Number(getAttrByName(attacker.id, 'str_i')); let Magi = Number(getAttrByName(attacker.id, 'mag_i')); let Skli = Number(getAttrByName(attacker.id, 'skl_i')); let Spdi = Number(getAttrByName(attacker.id, 'spd_i')); let Lcki = Number(getAttrByName(attacker.id, 'lck_i')); let Defi = Number(getAttrByName(attacker.id, 'def_i')); let Resi = Number(getAttrByName(attacker.id, 'res_i')); let sprefix = [HPi,Stri,Magi,Skli,Spdi,Lcki,Defi,Resi]; let HPSG = findObjs({ characterid: attacker.id, name: "HP_i", type: "attribute"})[0]; let StrSG = findObjs({ characterid: attacker.id, name: "Str_i", type: "attribute"})[0]; let MagSG = findObjs({ characterid: attacker.id, name: "Mag_i", type: "attribute"})[0]; let SklSG = findObjs({ characterid: attacker.id, name: "Skl_i", type: "attribute"})[0]; let SpdSG = findObjs({ characterid: attacker.id, name: "Spd_i", type: "attribute"})[0]; let LckSG = findObjs({ characterid: attacker.id, name: "Lck_i", type: "attribute"})[0]; let DefSG = findObjs({ characterid: attacker.id, name: "Def_i", type: "attribute"})[0]; let ResSG = findObjs({ characterid: attacker.id, name: "Res_i", type: "attribute"})[0]; let statslist = [HPSG,StrSG,MagSG,SklSG,SpdSG,LckSG,DefSG,ResSG]; log(statslist); let slist = ["HP","Str","Mag","Skl","Spd","Lck","Def","Res"]; for (var i = 0; i < growthslist.length - 1; i++){ gi = growthslist[i]; log(gi); if (randomInteger(100) < gi){ statslist[i].setWithWorker({current: sprefix[i] + 1}); if (gi > 100){ if (randomInteger(100) < gi){ Lvstr += "\n + 2 to "+ slist[i] + "!"; statslist[i].setWithWorker({current: sprefix[i] + 2}); } else{ Lvstr += "\n + 1 to "+ slist[i] + "!"; } } else { Lvstr += "\n + 1 to "+ slist[i] + "!"; } } } log(Lvstr); sendChat(who,Lvstr); } } }); //turn on("change:campaign:turnorder", function(turn) { var turnorder; var turncounter; if (Campaign().get("turnorder") == "") turnorder = []; else turnorder = JSON.parse(Campaign().get("turnorder")); for (var i in turnorder){ if (turnorder[i].custom == "Turn Counter"){ turncounter = turnorder[i] } } if (turnorder[0] !== turncounter){ //STRICT EQUALITY checking for if it's the turncounter's "turn" return; } let n = turncounter.pr ||0 log(turncounter) log(n) Skills = filterObjs(function(obj) { if (obj.get('type') !== 'ability' || obj.get('action').indexOf('"triggertime": "turn"') == -1) return false; return obj; }); log(Skills) if (Skills != []){ for (i in Skills){ let id = Skills[i].get('characterid'); Skills[i] = JSON.parse(Skills[i].get("action")); Skills[i]["ID"] = id; } } else { return; } log(Skills) //Skills system, user-centric version let user; let RNGSklU; let RNGLuckU; let CurrHPU; let HPU; let StrU; let MagU; let SklU; let SpdU; let LckU; let DefU; let ResU; let HitU; let CritU; let AvoU; let DdgU; let DdgE; let DmgU; let DmgtypeU; let PhysmagU; let PhysmaginvU; let HPA; let CurrHPA; function Skill(userid, obj, triggertime) { //haha END ME if (typeof obj != "object") { log("obj is not an object :(") return; } if (obj.triggertime != "turn"){ //JUST making sure return; } //no whotriggered checking because it'll always be the attacker log("Okay, first barrier passed") user = "attacker"; RNGSklU = Number(getAttrByName(userid, 'skl_total')); RNGLckU = Number(getAttrByName(userid, 'lck_total')); CurrHPU = findObjs({ characterid: userid, name: "HP_current" })[0]; let who = findObjs({ //get the first token on the page that represents the given user type: "character", id: userid })[0].get("name") || "User" HPA = Number(getAttrByName(userid, 'hp_current')); DmgtypeU = "" DmgtypeE = "" //doesn't matter since commands are non-combative anyways Usertoken = findObjs({ //get the first token on the page that represents the given user type: "graphic", subtype: "token", represents: userid })[0]; //stat definitions HPU = findObjs({ characterid: userid, name: "HP_bd" })[0]; StrU = findObjs({ characterid: userid, name: "Str_bd" })[0]; MagU = findObjs({ characterid: userid, name: "Mag_bd" })[0]; SklU = findObjs({ characterid: userid, name: "Skl_bd" })[0]; SpdU = findObjs({ characterid: userid, name: "Spd_bd" })[0]; LckU = findObjs({ characterid: userid, name: "Lck_bd" })[0]; DefU = findObjs({ characterid: userid, name: "Def_bd" })[0]; ResU = findObjs({ characterid: userid, name: "Res_bd" })[0]; //nice stat-variables for use in expressions and such let HP_StatU = getAttrByName(userid, 'hp_total'); let HP_CurrU = getAttrByName(userid, 'hp_current'); let Str_StatU = getAttrByName(userid, 'str_total'); let Mag_StatU = getAttrByName(userid, 'mag_total'); let Skl_StatU = getAttrByName(userid, 'skl_total'); let Spd_StatU = getAttrByName(userid, 'spd_total'); let Lck_StatU = getAttrByName(userid, 'lck_total'); let Def_StatU = getAttrByName(userid, 'def_total'); let Res_StatU = getAttrByName(userid, 'res_total'); let rng; if (obj.rng == "Skill") { rng = RNGSklU; } if (obj.rng == "Luck") { rng = RNGLckU; } if ((obj.customcond != "none") && (eval(obj.customcond) != true)) { return; } if ((obj.turncond != "none") && (eval(obj.turncond) != true)) { return; } log(obj.rng) //actual skill function function skillMain() { //No Physmag :O /* Parse damage and HP modifiers- normally eval() is incredibly dangerous and usually Shouldn't Be Used Under Any Circumstance Ever, but the Roll20 API sandboxes it, so I think it should be alright. Oh well!*/ let HealmodU = parseInt(eval(obj.u_healfactor)); log("HealmodU is" + HealmodU) let statnames = ["HP", "Str", "Mag", "Skl", "Spd", "Lck", "Def", "Res"]; //determining the actual stat target if (obj.u_stat_target != "none") { for (var r in statnames) { if (obj.u_stat_target == statnames[r]) { StattargetU = eval(statnames[r] + "U"); } } } let StattargetmodU = eval(obj.u_stat_targetmod); if (obj.u_stat_target != "none") { StattargetU.setWithWorker({ current: Number(StattargetU.get("current")) + Number(StattargetmodU) }); log("Set targeted stat to " + StattargetU.get("current")); } HPA = parseInt(HPA) + HealmodU; //this has to be here because sometimes it'll be stupid and overflow if it's not >:( log(HPA) if (obj.radius != 0) { //tortured screaming let tokenInRadius = filterObjs(function(token) { if ((token.get('type') !== 'graphic' || token.get('subtype') !== 'token' || token.get('represents') == "") || ManhDist(Usertoken, token) > obj.radius || token.get("represents") == Usertoken.get("represents")) return false; else return true; }); log("Tokens in radius are: ") for (var i in tokenInRadius) { log(tokenInRadius[i]) //stat targets let char = tokenInRadius[i].get("represents") let HPcurrC = findObjs({ characterid: char, name: "HP_current" })[0]; let StrC = findObjs({ characterid: char, name: "Str_bd" })[0]; let MagC = findObjs({ characterid: char, name: "Mag_bd" })[0]; let SklC = findObjs({ characterid: char, name: "Skl_bd" })[0]; let SpdC = findObjs({ characterid: char, name: "Spd_bd" })[0]; let LckC = findObjs({ characterid: char, name: "Lck_bd" })[0]; let DefC = findObjs({ characterid: char, name: "Def_bd" })[0]; let ResC = findObjs({ characterid: char, name: "Res_bd" })[0]; let HitC = findObjs({ characterid: char, name: "Hitmod" })[0]; let CritC = findObjs({ characterid: char, name: "Critmod" })[0]; let AvoC = findObjs({ characterid: char, name: "Avomod" })[0]; let DdgC = findObjs({ characterid: char, name: "Ddgmod" })[0]; //numerical stats let HPcurrStat = getAttrByName(char, 'HP_current'); let StrStat = getAttrByName(char, 'Str_total'); let MagStat = getAttrByName(char, 'Mag_total'); let SklStat = getAttrByName(char, 'Skl_total'); let SpdStat = getAttrByName(char, 'Spd_total'); let LckStat = getAttrByName(char, 'Lck_total'); let DefStat = getAttrByName(char, 'Def_total'); let ResStat = getAttrByName(char, 'Res_total'); let HitStat = getAttrByName(char, 'Hit'); let CritStat = getAttrByName(char, 'Crit'); let AvoStat = getAttrByName(char, 'Avo'); let DdgStat = getAttrByName(char, 'Ddg'); let effect = eval(obj.radius_effect); //effect MUST be an array!!! let rad_effect = Number(effect[0].get("current")) + parseInt(Number(effect[1])) log(effect[0].get("current")) effect[0].setWithWorker({ current: rad_effect }); log(effect[0].get("current")) if ((effect[0] == HPcurrC) && (char == userid)) { HPA += parseInt(effect[1]) } } } CurrHPU.setWithWorker({ current: HPA }); //recursionnn if (obj.children_skills != []) { for (var y in obj.children_skills) { let Child_Skill = JSON.parse(obj.children_skills[y]); Skill(userid, Child_Skill, "any"); //child implementations of preexisting skills should have the triggertime "any" as well } } let Chatstr; if (obj.custom_string != "") { Chatstr = '' + obj.custom_string + "\n" } else { Chatstr = '' + obj.name + " activated!\n" } sendChat(who, Chatstr); } if (obj.rng != "none") { if (randomInteger(100) < (rng * obj.rngmod)) { skillMain(); } else { log("RIP RNG") return; } } else { //Plain ol' skill trigger log("Regular skillmain") skillMain(); } } for (var j in Skills){ Skill(Skills[i].ID, Skills[i], "turn") } });